/*
 *       This file is part of VFC.
 *
 *        VFC is free software: you can redistribute it and/or modify
 *        it under the terms of the GNU General Public License as published by
 *        the Free Software Foundation, either version 3 of the License, or
 *        (at your option) any later version.
 *
 *        VFC is distributed in the hope that it will be useful,
 *        but WITHOUT ANY WARRANTY; without even the implied warranty of
 *        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *        GNU General Public License for more details.
 *
 *        You should have received a copy of the GNU General Public License
 *        along with VFC.  If not, see <http://www.gnu.org/licenses/>.
 */


/*
 *      Status Register
 *      [N V 1 B D I Z C]
 * 
 * C - Carry Flag           : Set when Accumulator rolls over from 0xff to 0x00.
 * Z - Zero Flag            : Set when any operations result is zero.
 * I - Interrupt Mask       : Prevents Interrupt when set.
 * D - Decimal Flag         : Used by 6502, set when 6502 does arithmetic in BCD.
 *                            Since RP2A03 lacks BCD operaton, this is just ignored.
 * B - Break Flag           : Set whenever BRK instruction is executed. Clear at all times.
 * 1 - No Name              : Always set to 1.
 * V - Overflow Flag        : Important in two's compliment, elsewhere it is rarely used.
 * N - Negative Flag        : Matches the high bit of the result of whatever operation is executed.
 */

using System;
using System.Collections.Generic;
using System.Text;

namespace VFC.Nes.Cpu
{
    class Register
    {
        public static int X;       //X Register
        public static int Y;       //Y Register
        public static int A;       //Accumulator
        public static int PC;      //Program Counter
        public static int SR;      //Status Register
        public static int SP;      //Stack Pointer

        public static void Init()
        {
            X = 0x00;
            Y = 0x00;
            A = 0x00;
            PC = 0x00;
            SR = 0x24;
            SP = 0xfd;
        }

        /*
         * Carry Flag Operation (Status Register)
         *      
         */

        public static void SetCarryFlag()
        {
            SR |= 0x01;
        }

        public static void ClearCarryFlag()
        {
            SR &= 0xfe;
        }

        public static int GetCarryFlag()
        {
            return SR & 0x01;
        }

        /*
         * Zero Flag Operation
         */
        public static void SetZeroFlag()
        {
            SR |= 0x02;
        }

        public static void ClearZeroFlag()
        {
            SR &= 0xfd;
        }

        public static int GetZeroFlag()
        {
            return (SR & 0x02) >> 0x01;
        }

        /*
         * Interrupt Flag Operation
         */
        public static void SetInterruptFlag()
        {
            SR |= 0x04;
        }

        public static void ClearInterruptFlag()
        {
            SR &= 0xfb;
        }

        public static int GetInterruptFlag()
        {
            return (SR & 0x04) >> 0x02;
        }

        /*
         * Break Flag Operation
         */
        public static void SetBreakFlag()
        {
            SR |= 0x10;
        }

        public static void ClearBreakFlag()
        {
            SR &= 0xef;
        }

        public static int GetBreakFlag()
        {
            return (SR & 0x10) >> 0x04;
        }

        /*
         * Overflow Flag Operation
         */
        public static void SetOverflowFlag()
        {
            SR |= 0x40;
        }

        public static void ClearOverflowFlag()
        {
            SR &= 0xbf;
        }

        public static int GetOverflowFlag()
        {
            return (SR & 0x40) >> 0x06;
        }

        /*
         * Negative Flag Operation
         */
        public static void SetNegativeFlag()
        {
            SR |= 0x80;
        }

        public static void ClearNegativeFlag()
        {
            SR &= 0x7f;
        }

        public static int GetNegativeFlag()
        {
            return (SR & 0x80) >> 0x07;
        }

        /*
         * Decimal Flag Operation
         */
        public static void SetDecimalFlag()
        {
            SR |= 0x08;
        }

        public static void ClearDecimalFlag()
        {
            SR &= 0xf7;
        }

        public static int GetDecimalFlag()
        {
            return (SR & 0x08) >> 0x03;
        }
    }
}
